home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / 3DDEMO.ZIP / 3D / SOURCE / MESH.CPP < prev    next >
C/C++ Source or Header  |  1996-07-23  |  58KB  |  1,866 lines

  1. #include "mesh.hpp"
  2.  
  3. // Copyright (c) 1996 by Kerrigan Burgess, all rights reserved.
  4.  
  5.  
  6. int SHADING;                       // flag. which type? (Constant,Gouraud,Phong,Flat).
  7. int TEXTUREMAPPED;                 // flag. Is it Texture Mapped?
  8. int TRANSPARENCY;                  // flag. Is it enabled? (opaque/transparent).
  9. int MORPHING;                      // flag. Is it enabled?
  10. int SHADOWING;                     // flag. Are shadows enabled?      
  11. int HAZING;                        // flag. Is hazing on?
  12.  
  13. POLYGONCLASS **MeshList;             // for final rendering.
  14. int meshindex;                       // index for MeshList.
  15. int shadowindex;                     // how many shadows per frame.
  16.  
  17. void ComputeAvgZ(void)
  18. {
  19.   int count;
  20.   POLYGONCLASS *ThisPolygon;
  21.   
  22.   for (count=shadowindex;count<meshindex;count++)
  23.   {
  24.      ThisPolygon = MeshList[count];
  25.      ThisPolygon->avgz=(float)0.33333*( (ThisPolygon->Vertex[0])->z +
  26.                                           (ThisPolygon->Vertex[1])->z +
  27.                                              (ThisPolygon->Vertex[2])->z );
  28.   }
  29. }
  30.  
  31. int PolyCompare(const void *arg1, const void *arg2)
  32. {
  33.    POLYGONCLASS *Poly1,*Poly2;
  34.  
  35.    Poly1=*(POLYGONCLASS **)arg1;
  36.    Poly2=*(POLYGONCLASS **)arg2;
  37.       
  38.    if (Poly1->avgz > Poly2->avgz)
  39.      return (-1);
  40.    else
  41.    if (Poly1->avgz < Poly2->avgz)
  42.      return (1);
  43.    else
  44.      return (0);
  45. }
  46.  
  47. LIGHTCLASS::LIGHTCLASS(void)           // Constructor.
  48. {   
  49.    lightsource.x=0;          // light is at origin.
  50.    lightsource.y=0;
  51.    lightsource.z=0;
  52. }
  53.  
  54. LIGHTCLASS::~LIGHTCLASS(void)          // Destructor.
  55. {
  56.  
  57. }
  58.  
  59. LIGHTCLASS::SetLight(float x, float y, float z)
  60. {
  61.     // set light in world coords.
  62.  
  63.   lightsource.x=x;
  64.   lightsource.y=y;
  65.   lightsource.z=z;
  66.  
  67.   infinitelightsource.x=x;
  68.   infinitelightsource.y=y;
  69.   infinitelightsource.z=z*1000;       // set it pretty dammed far.
  70. }
  71.  
  72. POINT3D *LIGHTCLASS::GetLight(void)
  73. {  
  74.   return (&lightsource);
  75. }
  76.  
  77. POINT3D *LIGHTCLASS::GetInfiniteLight(void)
  78. {
  79.   return (&infinitelightsource);
  80. }
  81.  
  82. CAMERACLASS::CAMERACLASS(void)         // Constructor.
  83. {
  84.   viewpoint.x=0;
  85.   viewpoint.y=0;
  86.   viewpoint.z=0;
  87.   angx=0;
  88.   angy=0;
  89.   angz=0;
  90. }
  91.  
  92. CAMERACLASS::~CAMERACLASS(void)         // Destructor.
  93. {
  94.  
  95. }
  96.  
  97. void CAMERACLASS::SetViewPoint(float viewx, float viewy, float viewz)
  98. {
  99.    viewpoint.x = viewx;
  100.    viewpoint.y = viewy;
  101.    viewpoint.z = viewz; 
  102. }
  103.  
  104. void CAMERACLASS::MoveViewPoint(float viewx, float viewy, float viewz)
  105. {
  106.    viewpoint.x+=viewx;
  107.    viewpoint.y+=viewy;
  108.    viewpoint.z+=viewz;
  109. }
  110.  
  111. POINT3D *CAMERACLASS::GetViewPoint(void)
  112. {
  113.   return (&viewpoint);
  114. }
  115.  
  116. void CAMERACLASS::SetViewAngle(int angle_x, int angle_y, int angle_z)
  117. {
  118.     angx=angle_x;
  119.     angy=angle_y;
  120.     angz=angle_z;
  121. }
  122.  
  123. void CAMERACLASS::MoveViewAngle(int angle_x, int angle_y, int angle_z)
  124. {
  125.    angx+=angle_x;
  126.    angy+=angle_y;     
  127.    angz+=angle_z;
  128. }
  129.  
  130. void CAMERACLASS::CreateCameraMatrix(MATRIX CameraMatrix)
  131. {
  132.   double Xa,Ya,Za;
  133.   float Sx,Cx,Sy,Cy,Sz,Cz;
  134.  
  135.     // Change degree to radian
  136.   Xa = -angx*6.281/360;
  137.   Ya = -angy*6.281/360;
  138.   Za = -angz*6.281/360;
  139.     
  140.   Sx = (float)sin ( Xa );
  141.   Cx = (float)cos ( Xa );
  142.   Sy = (float)sin ( Ya );
  143.   Cy = (float)cos ( Ya );
  144.   Sz = (float)sin ( Za );
  145.   Cz = (float)cos ( Za );
  146.  
  147. //T*Y*X*Z;
  148.        CameraMatrix[0][0] = Cy*Cz+Sy*Sx*Sz;
  149.        CameraMatrix[0][1] = -Cy*Sz+Sy*Sx*Cz;
  150.        CameraMatrix[0][2] = Sy*Cx;    
  151.        CameraMatrix[0][3] = 0;
  152.  
  153.        CameraMatrix[1][0] = Cx*Sz;
  154.        CameraMatrix[1][1] = Cx*Cz;
  155.        CameraMatrix[1][2] = -Sx;
  156.        CameraMatrix[1][3] = 0;
  157.  
  158.        CameraMatrix[2][0] = -Sy*Cz+Cy*Sx*Sz;
  159.        CameraMatrix[2][1] = Sy*Sz+Cy*Sx*Cz;
  160.        CameraMatrix[2][2] = Cy*Cx;
  161.        CameraMatrix[2][3] = 0;
  162.  
  163.        CameraMatrix[3][0] = -viewpoint.x*(Cy*Cz+Sy*Sx*Sz) 
  164.                             -viewpoint.y*(Cx*Sz)
  165.                             -viewpoint.z*(-Sy*Cz+Cy*Sx*Sz);
  166.        CameraMatrix[3][1] = -viewpoint.x*(-Cy*Sz+Sy*Sx*Cz)
  167.                             -viewpoint.y*(Cx*Cz)
  168.                             -viewpoint.z*(Sy*Sz+Cy*Sx*Cz);
  169.        CameraMatrix[3][2] = -viewpoint.x*(Sy*Cx)
  170.                             -viewpoint.y*(-Sx)
  171.                             -viewpoint.z*(Cy*Cx);
  172.        CameraMatrix[3][3] = 1;
  173. }
  174.  
  175. MESHCLASS::MESHCLASS(void)           // constructor.
  176. {
  177.   ObjectHead = NULL;
  178.  
  179.   meshindex=0;                              // index for rendering list.
  180.   shadowindex=0;                            // how shadows in frame.
  181.   totalfaces=0;
  182.   
  183.   MAX_LIGHTS  = 1;
  184.   Light  = new  LIGHTCLASS [MAX_LIGHTS];
  185.  
  186.   Light[0].SetLight(0,0,-1);
  187.   
  188.  _CURRENTCAMERA_ = 0;
  189.   MAX_CAMERAS = 4;
  190.   Camera = new CAMERACLASS [MAX_CAMERAS];
  191.  
  192.   int count;
  193.   for (count=0;count<MAX_CAMERAS;count++)
  194.     Camera[count] = CAMERACLASS();       // call constructor to initialize
  195.  
  196.   velangx=0;
  197.   velangy=0;
  198.   velangz=0;
  199.   angx=0;                  // initialize rotation angles.
  200.   angy=0;
  201.   angz=0;
  202.   tx=ty=tz=0;              // initialize translation vectors.
  203.  
  204.   translevel=0;             // start no transparency.
  205.  
  206.   MORPHING=FALSE;            // set morph to False.
  207.   SHADING = Gouraud;         // default to Gouraud shading.
  208.   TEXTUREMAPPED = NoTexture; // default to no texture.
  209.   TRANSPARENCY = Opaque;     // shut off transparency.
  210.   SHADOWING = NoShadow;      // disable shadow mapping.
  211.   HAZING = NoHaze;           // shut off hazing.
  212.  
  213.   HITHER_Z = 10;             // default Z clipping at these values.
  214.   YON_Z = 1000;
  215. }
  216.  
  217. MESHCLASS::~MESHCLASS(void)          // destructor.
  218. {
  219.   if (Light != NULL)  
  220.     delete Light;
  221.   if (Camera != NULL)  
  222.     delete Camera;
  223.   if (ObjectHead != NULL)
  224.     delete ObjectHead;
  225.   if (MeshList != NULL)
  226.     delete MeshList;
  227. }
  228.  
  229. void MESHCLASS::CreateMeshList(void)
  230. {
  231.     if (MeshList != NULL)
  232.       delete MeshList;
  233.     MeshList = new POLYGONCLASS *[totalfaces];  // need to allocate for MeshList.
  234.     if (MeshList==NULL)
  235.       Error("Not enough memory\n");
  236. }
  237.  
  238. void MESHCLASS::ResetOrigin(void)          // put mesh back to 0,0,0 (world coords)
  239. {
  240.    Camera[_CURRENTCAMERA_].SetViewAngle(0,0,0);
  241.    Camera[_CURRENTCAMERA_].SetViewPoint(0,0,0);
  242. }
  243.   
  244. void MESHCLASS::SetMaxTransparency(int Levels)
  245. {
  246.   MaxTransLevel = Levels;
  247. }
  248.  
  249. void MESHCLASS::SetTransparencyLevel(int delta)
  250. {
  251.    if (HAZING)          // can't have both transparency and hazing.
  252.      return;
  253.          
  254.    translevel+=delta;
  255.    TRANSPARENCY=Transparent;
  256.  
  257.    if (translevel<0)
  258.    {
  259.      translevel=-1;
  260.      TRANSPARENCY=Opaque;      // fully visible.
  261.    }
  262.    else
  263.    if (translevel>MaxTransLevel)
  264.    {
  265.      translevel=MaxTransLevel;
  266.    }
  267. }
  268.  
  269. void MESHCLASS::SetShading(int Shade)
  270. {
  271.    SHADING = Shade;
  272. }
  273.  
  274. void MESHCLASS::SetTextureMapping(int mode)
  275. {
  276.    TEXTUREMAPPED = mode;
  277. }
  278.  
  279. void MESHCLASS::SetHazing(int mode)
  280. {    
  281.    HAZING = mode;
  282.    TRANSPARENCY=Opaque;             // shut off.
  283. }
  284.  
  285. void MESHCLASS::SetTransparency(int mode)
  286. {
  287.    TRANSPARENCY=mode;
  288.    HAZING=NoHaze;                   // shut off.
  289. }
  290.  
  291. void MESHCLASS::SetMorph(int mode)
  292. {
  293.   MORPHING = mode;
  294. }
  295.  
  296. void MESHCLASS::SetShadow(int Mode)
  297. {
  298.   SHADOWING = Mode;
  299. }
  300.  
  301. void MESHCLASS::SetTSRVectors(int angle_x, int angle_y, int angle_z,
  302.                                int transx, int transy, int transz)
  303. {
  304.    velangx+=angle_x;           // change velocity of rotation angles.
  305.    velangy+=angle_y;
  306.    velangz+=angle_z;
  307.  
  308.    tx=transx;
  309.    ty=transy;
  310.    tz=transz;
  311. }
  312.  
  313. void MESHCLASS::ResetTSRVectors(void)
  314. {
  315.   velangx=0;
  316.   velangy=0;
  317.   velangz=0;
  318.   
  319.   angx=0;              
  320.   angy=0;
  321.   angz=0;
  322.  
  323.   tx=ty=tz=0;
  324. }
  325.  
  326. void MESHCLASS::MoveCamera(int angle_x, int angle_y, int angle_z,
  327.                             float viewx, float viewy, float viewz)
  328. {
  329.    Camera[_CURRENTCAMERA_].MoveViewAngle(angle_x,angle_y,angle_z);
  330.    Camera[_CURRENTCAMERA_].MoveViewPoint(viewx,viewy,viewz);
  331. }
  332.  
  333. void MESHCLASS::_3DPipeLine(void)
  334. {
  335.    Camera[_CURRENTCAMERA_].CreateCameraMatrix(CameraMatrix);
  336.    CreateTSR_Matrix();
  337.    ObjectCull(CULL_XYZ);
  338.    DepthSort();
  339.    Render();
  340. }
  341.  
  342. void MESHCLASS::Push(OBJECTCLASS *ThisObject,int Status)
  343. {
  344.  
  345.   switch (Status)
  346.   {
  347.      case PARENT:
  348.  
  349.        if (ObjectHead == NULL)        // first object.
  350.        {
  351.          ObjectHead = ThisObject;
  352.          ThisObject->morphsteps = 1/(float)100;           // morph in 100 steps.
  353.          ThisObject->MorphSource = ThisObject;            // reset Starting morph to Parent.
  354.          ThisObject->NextMorphObject = ThisObject;        // point back to itself for circular list.     
  355.        }
  356.        else
  357.        {
  358.          OBJECTCLASS *temp;
  359.          temp = ObjectHead;
  360.  
  361.          while (temp->NextObject != NULL)
  362.            temp = temp->NextObject;
  363.  
  364.          ThisObject->morphsteps = 1/(float)100;           // morph in 100 steps.
  365.          ThisObject->MorphSource = ThisObject;            // reset Starting morph to Parent.
  366.          ThisObject->NextMorphObject = ThisObject;        // point back to itself for circular list.     
  367.          temp->NextObject = ThisObject;
  368.        }
  369.      break;
  370.  
  371.      case CHILD:
  372.        if (ObjectHead == NULL)
  373.        {
  374.           Error("Trying to initialize CHILD without PARENT\n");
  375.        }
  376.        else
  377.        {
  378.           OBJECTCLASS *temp, temp2;
  379.           temp = ObjectHead;
  380.           
  381.           while (temp->NextObject != NULL)
  382.             temp = temp->NextObject;
  383.  
  384.           ThisObject->NextMorphObject = temp->NextMorphObject;  // point back to parent. Circular list.  
  385.           temp->NextMorphObject = ThisObject;
  386.        }
  387.      break;
  388.   }
  389. }
  390.  
  391. int MESHCLASS::SetWorldXYZ(int ObjectID,float wx,float wy,float wz)
  392. {
  393.   OBJECTCLASS *temp;
  394.  
  395.   temp=ObjectHead;
  396.  
  397.   while ( (temp != NULL) && (temp->ObjectID != ObjectID) )
  398.   {
  399.     OBJECTCLASS *temp2;
  400.     
  401.       temp2=temp->NextMorphObject;
  402.       while ( (temp2 != temp) && (temp2->ObjectID != ObjectID) )  // Search Children.
  403.         temp2=temp2->NextMorphObject;
  404.  
  405.       if (temp2->ObjectID == ObjectID)
  406.       {
  407.         temp2->worldx = wx;
  408.         temp2->worldy = wy;
  409.         temp2->worldz = wz;
  410.         return (SUCCESS);
  411.       }      
  412.     temp=temp->NextObject;
  413.   }
  414.   
  415.   if (temp->ObjectID == ObjectID)
  416.   {
  417.     temp->worldx = wx;
  418.     temp->worldy = wy;
  419.     temp->worldz = wz;
  420.    return (SUCCESS);
  421.   }
  422.   else
  423.     return (FAILURE);
  424. }
  425.  
  426. void MESHCLASS::SetCurrentCamera(int camera)
  427. {
  428.    _CURRENTCAMERA_ = camera;
  429. }
  430.  
  431. void MESHCLASS::ObjectCull(int Mode)
  432. {
  433.    OBJECTCLASS *ThisObject;
  434.    float radius;
  435.    float xsphere,ysphere,zsphere,xcompare,ycompare;
  436.  
  437.    ThisObject=ObjectHead;       // point to head of list.
  438.    meshindex=0;                 // reset, for MeshList.
  439.    shadowindex=0;               // reset how many shadows.
  440.    
  441.    POINT3D *viewpoint, *lightsource, *infinitelightsource;
  442.    viewpoint=Camera[_CURRENTCAMERA_].GetViewPoint();
  443.    lightsource=Light[0].GetLight();
  444.    infinitelightsource=Light[0].GetInfiniteLight();
  445.  
  446.  
  447. //   if (MORPHING)                        // These 2 lines are only for the demo purposes because
  448. //     ThisObject=ThisObject->NextObject;  // I only want the 2nd Parent object to morph not the first.
  449.                                          // Take these lines out for your own implementation and remove ( // ) from while statement and continues.
  450.  
  451.    while ( ThisObject != NULL)
  452.    {
  453.  
  454.       ThisObject=ThisObject->GetMorphObject();   // if morph enabled, return object else return root object.
  455.  
  456.       ThisObject->Local2Camera(CameraMatrix, CENTER);   // 1 means use world pos to transform.
  457.       ThisObject->GetCenterStats(&radius,&xsphere,&ysphere,&zsphere);
  458.  
  459.       switch (Mode)
  460.       {
  461.          case CULL_Z:
  462.            if ( ((zsphere-radius) > YON_Z) ||
  463.                 ((zsphere+radius) < HITHER_Z) )
  464.              {
  465.                 ThisObject=ThisObject->NextObject;
  466.                 continue;               // Not visible!
  467.              }
  468.            else
  469.              { 
  470.                 ThisObject->TransformObject(TSR_Matrix);
  471.                 ThisObject->Local2Camera(CameraMatrix,VERTICES);    
  472.                 ThisObject->HSR_Shade(viewpoint,lightsource);
  473.                 ThisObject->DoShadows(infinitelightsource);
  474.                 ThisObject->PolyCull(Mode);
  475.              }
  476.          break;
  477.  
  478.          case CULL_XYZ:
  479.            if ( ((zsphere-radius) > YON_Z) ||
  480.                 ((zsphere+radius) < HITHER_Z) )
  481.              {          
  482.                 ThisObject=ThisObject->NextObject;
  483.                 continue;
  484.              }
  485.              
  486.            xcompare = HALF_SCREEN_WIDTH_VD*zsphere;
  487.            if ( ((xsphere-radius) > xcompare) ||
  488.                 ((xsphere+radius) < -xcompare) )
  489.               {        
  490.                 ThisObject=ThisObject->NextObject;
  491.                 continue;
  492.               }
  493.  
  494.            ycompare = HALF_SCREEN_HEIGHT_VD*zsphere;
  495.            if ( ((xsphere-radius) > ycompare) ||
  496.                 ((xsphere+radius) < -ycompare) )
  497.               {
  498.                 ThisObject=ThisObject->NextObject;
  499.                 continue;
  500.               }            // It passed all tests --> object is visible.
  501.                 
  502.               ThisObject->TransformObject(TSR_Matrix);
  503.               ThisObject->Local2Camera(CameraMatrix,VERTICES);  
  504.               ThisObject->HSR_Shade(viewpoint,lightsource);
  505.               ThisObject->DoShadows(infinitelightsource);
  506.               ThisObject->PolyCull(Mode);
  507.            break;
  508.       default:
  509.         break;
  510.       }  // end switch.
  511.      ThisObject=ThisObject->NextObject;
  512.    } // end while.
  513. }
  514.  
  515. void MESHCLASS::CreateTSR_Matrix(void)
  516. {
  517.   double Xa,Ya,Za;
  518.   float Sx,Cx,Sy,Cy,Sz,Cz;
  519.  
  520.   angx+=velangx;
  521.   angy+=velangy;
  522.   angz+=velangz;
  523.  
  524.   Xa = -angx*DEGREES_TO_RADIANS;
  525.   Ya = -angy*DEGREES_TO_RADIANS;
  526.   Za = -angz*DEGREES_TO_RADIANS;
  527.     
  528.   Sx = (float)sin ( Xa );
  529.   Cx = (float)cos ( Xa );
  530.   Sy = (float)sin ( Ya );
  531.   Cy = (float)cos ( Ya );
  532.   Sz = (float)sin ( Za );
  533.   Cz = (float)cos ( Za );
  534.  
  535.   TSR_Matrix[0][0] = Cy*Cz;
  536.   TSR_Matrix[0][1] = Cy*Sz;
  537.   TSR_Matrix[0][2] = -Sy;
  538.   TSR_Matrix[0][3] = 0;
  539.  
  540.   TSR_Matrix[1][0] = Sx*Sy*Cz-Cx*Sz;
  541.   TSR_Matrix[1][1] = Sx*Sy*Sz+Cx*Cz;
  542.   TSR_Matrix[1][2] = Sx*Cy;
  543.   TSR_Matrix[1][3] = 0;
  544.  
  545.   TSR_Matrix[2][0] = Cx*Sy*Cz+Sx*Sz;
  546.   TSR_Matrix[2][1] = Cx*Sy*Sz-Sx*Cz;
  547.   TSR_Matrix[2][2] = Cx*Cy;
  548.   TSR_Matrix[2][3] = 0;
  549.  
  550. }
  551.  
  552. void MESHCLASS::DepthSort(void)
  553. {
  554.   if (meshindex != 0)
  555.   {
  556.      ComputeAvgZ();
  557.      qsort( &(MeshList[shadowindex]), meshindex-shadowindex,
  558.                      sizeof( POLYGONCLASS *), PolyCompare );
  559.   }
  560. }
  561.  
  562. void MESHCLASS::Render(void)
  563. {
  564.     int pindex;
  565.     int SHADOW;
  566.     float x0,y0,z0,x1,y1,z1,x2,y2,z2;
  567.     POLYGONCLASS *ThisPolygon;
  568.     
  569.     for (pindex=0;pindex<meshindex;pindex++)
  570.     {
  571.       ThisPolygon = MeshList[pindex];       
  572.       SHADOW = ThisPolygon->shadowvisible;
  573.       
  574.       if (SHADOW)
  575.       {
  576.         x0 = (ThisPolygon->shadow[0]).x;
  577.         y0 = (ThisPolygon->shadow[0]).y;
  578.         z0 = (ThisPolygon->shadow[0]).z;
  579.  
  580.         x1 = (ThisPolygon->shadow[1]).x;
  581.         y1 = (ThisPolygon->shadow[1]).y;
  582.         z1 = (ThisPolygon->shadow[1]).z;
  583.  
  584.         x2 = (ThisPolygon->shadow[2]).x;
  585.         y2 = (ThisPolygon->shadow[2]).y;
  586.         z2 = (ThisPolygon->shadow[2]).z;
  587.  
  588.         ThisPolygon->shadowvisible = NoShadow;      // reset.
  589.       }
  590.       else
  591.       {
  592.         x0 = (ThisPolygon->Vertex[0])->x;
  593.         y0 = (ThisPolygon->Vertex[0])->y;
  594.         z0 = (ThisPolygon->Vertex[0])->z;
  595.  
  596.         x1 = (ThisPolygon->Vertex[1])->x;
  597.         y1 = (ThisPolygon->Vertex[1])->y;
  598.         z1 = (ThisPolygon->Vertex[1])->z;
  599.  
  600.         x2 = (ThisPolygon->Vertex[2])->x;
  601.         y2 = (ThisPolygon->Vertex[2])->y;
  602.         z2 = (ThisPolygon->Vertex[2])->z;
  603.       }
  604.  
  605.       long ix1,iy1,ix2,iy2,ix3,iy3;
  606.       
  607.         _X1  = ix1 = (long)(HALF_SCREEN_WIDTH + x0*VIEWDISTANCE/z0);
  608.         _Y1  = iy1 = (long)(HALF_SCREEN_HEIGHT - y0*VD_ASPECTRATIO/z0);
  609.  
  610.         _X2  = ix2 = (long)(HALF_SCREEN_WIDTH + x1*VIEWDISTANCE/z1);
  611.         _Y2  = iy2 = (long)(HALF_SCREEN_HEIGHT - y1*VD_ASPECTRATIO/z1);
  612.  
  613.         _X3  = ix3 = (long)(HALF_SCREEN_WIDTH + x2*VIEWDISTANCE/z2);
  614.         _Y3  = iy3 = (long)(HALF_SCREEN_HEIGHT - y2*VD_ASPECTRATIO/z2);
  615.  
  616.       switch ( TEXTUREMAPPED | SHADING | TRANSPARENCY | SHADOW | HAZING )
  617.       {
  618.          case WireFrame:
  619.              _ColorIndex=ThisPolygon->color+SHADES;          
  620.              Scan_Convert_Wire();
  621.          break;
  622.          
  623.          case Constant:
  624.              _ColorIndex = ThisPolygon->color + (ThisPolygon->Vertex[0])->Intensity;
  625.              Scan_Convert_Lambert();
  626.          break;
  627.  
  628.          case Lambert: 
  629.              _ColorIndex = ThisPolygon->color + (ThisPolygon->Vertex[0])->Intensity;
  630.               Scan_Convert_Lambert();
  631.          break;
  632.  
  633.          case Gouraud:
  634.              _I1         = (ThisPolygon->Vertex[0])->Intensity;
  635.              _I2         = (ThisPolygon->Vertex[1])->Intensity;
  636.              _I3         = (ThisPolygon->Vertex[2])->Intensity;
  637.              _ColorIndex = ThisPolygon->color;
  638.              Scan_Convert_Gouraud();
  639.          break;
  640.  
  641.          case Phong:
  642.              _A1         = (ThisPolygon->Vertex[0])->Intensity;
  643.              _A2         = (ThisPolygon->Vertex[1])->Intensity;
  644.              _A3         = (ThisPolygon->Vertex[2])->Intensity;
  645.              _ColorIndex = ThisPolygon->color;
  646.              Scan_Convert_Phong();
  647.          break;
  648.          
  649.          case WireFrame_Texture:           // just call same function again.
  650.              _ColorIndex=ThisPolygon->color+SHADES;          
  651.              Scan_Convert_Wire();
  652.          break;
  653.  
  654.          case Constant_Texture:   
  655.              _U1         = ThisPolygon->u0;
  656.              _V1         = ThisPolygon->v0;
  657.              _U2         = ThisPolygon->u1;
  658.              _V2         = ThisPolygon->v1;
  659.              _U3         = ThisPolygon->u2;
  660.              _V3         = ThisPolygon->v2;
  661.              _ColorIndex = SHADES;
  662.              Scan_Convert_TextureL();
  663.          break;
  664.  
  665.          case Lambert_Texture:
  666.              _U1         = ThisPolygon->u0;
  667.              _V1         = ThisPolygon->v0;
  668.              _U2         = ThisPolygon->u1;
  669.              _V2         = ThisPolygon->v1;
  670.              _U3         = ThisPolygon->u2;
  671.              _V3         = ThisPolygon->v2;
  672.              _ColorIndex = (ThisPolygon->Vertex[0])->Intensity;
  673.              Scan_Convert_TextureL();
  674.          break;
  675.  
  676.          case Gouraud_Texture:
  677.              _U1       = ThisPolygon->u0;
  678.              _V1       = ThisPolygon->v0;
  679.              _U2       = ThisPolygon->u1;
  680.              _V2       = ThisPolygon->v1;
  681.              _U3       = ThisPolygon->u2;
  682.              _V3       = ThisPolygon->v2;
  683.              _I1       = (ThisPolygon->Vertex[0])->Intensity;
  684.              _I2       = (ThisPolygon->Vertex[1])->Intensity;
  685.              _I3       = (ThisPolygon->Vertex[2])->Intensity;
  686.              Scan_Convert_TextureG();
  687.          break; 
  688.  
  689.          case Phong_Texture:
  690.              _U1         = ThisPolygon->u0;
  691.              _V1         = ThisPolygon->v0;
  692.              _U2         = ThisPolygon->u1;
  693.              _V2         = ThisPolygon->v1;
  694.              _U3         = ThisPolygon->u2;
  695.              _V3         = ThisPolygon->v2;
  696.              _A1         = (ThisPolygon->Vertex[0])->Intensity;
  697.              _A2         = (ThisPolygon->Vertex[1])->Intensity;
  698.              _A3         = (ThisPolygon->Vertex[2])->Intensity;
  699.              Scan_Convert_TextureP();
  700.          break;
  701.  
  702.          case WireFrame_Trans:           
  703.              _ColorIndex=ThisPolygon->color+SHADES;          
  704.              Scan_Convert_Wire();
  705.          break;
  706.  
  707.          case Constant_Trans:   
  708.              _ColorIndex = ThisPolygon->color + (ThisPolygon->Vertex[0])->Intensity;
  709.              _TransLevel = translevel;
  710.              Scan_Convert_LambertT();
  711.          break;
  712.  
  713.          case Lambert_Trans:
  714.              _ColorIndex = ThisPolygon->color + (ThisPolygon->Vertex[0])->Intensity;
  715.              _TransLevel = translevel;
  716.              Scan_Convert_LambertT();
  717.          break;
  718.  
  719.          case Gouraud_Trans:
  720.              _I1         = (ThisPolygon->Vertex[0])->Intensity;
  721.              _I2         = (ThisPolygon->Vertex[1])->Intensity;
  722.              _I3         = (ThisPolygon->Vertex[2])->Intensity;
  723.              _ColorIndex = ThisPolygon->color;
  724.              _TransLevel = translevel;       
  725.              Scan_Convert_GouraudT();
  726.          break;
  727.  
  728.          case Phong_Trans:
  729.              _A1         = (ThisPolygon->Vertex[0])->Intensity;
  730.              _A2         = (ThisPolygon->Vertex[1])->Intensity;
  731.              _A3         = (ThisPolygon->Vertex[2])->Intensity;
  732.              _ColorIndex = ThisPolygon->color;
  733.              _TransLevel = translevel;       
  734.              Scan_Convert_PhongT();
  735.          break;
  736.          
  737.          case WireFrame_Texture_Trans:        
  738.              _ColorIndex=ThisPolygon->color+SHADES;          
  739.              Scan_Convert_Wire();
  740.          break;
  741.  
  742.          case Constant_Texture_Trans:   
  743.              _U1         = ThisPolygon->u0;
  744.              _V1         = ThisPolygon->v0;
  745.              _U2         = ThisPolygon->u1;
  746.              _V2         = ThisPolygon->v1;
  747.              _U3         = ThisPolygon->u2;
  748.              _V3         = ThisPolygon->v2;
  749.              _ColorIndex = SHADES;
  750.              _TransLevel = translevel;
  751.              Scan_Convert_TextureLT();
  752.          break;
  753.  
  754.          case Lambert_Texture_Trans:
  755.              _U1         = ThisPolygon->u0;
  756.              _V1         = ThisPolygon->v0;
  757.              _U2         = ThisPolygon->u1;
  758.              _V2         = ThisPolygon->v1;
  759.              _U3         = ThisPolygon->u2;
  760.              _V3         = ThisPolygon->v2;
  761.              _ColorIndex = (ThisPolygon->Vertex[0])->Intensity;
  762.              _TransLevel = translevel;
  763.              Scan_Convert_TextureLT();
  764.          break;
  765.  
  766.          case Gouraud_Texture_Trans:
  767.              _U1         = ThisPolygon->u0;
  768.              _V1         = ThisPolygon->v0;
  769.              _U2         = ThisPolygon->u1;
  770.              _V2         = ThisPolygon->v1;
  771.              _U3         = ThisPolygon->u2;
  772.              _V3         = ThisPolygon->v2;
  773.              _I1         = (ThisPolygon->Vertex[0])->Intensity;
  774.              _I2         = (ThisPolygon->Vertex[1])->Intensity;
  775.              _I3         = (ThisPolygon->Vertex[2])->Intensity;
  776.              _TransLevel = translevel;
  777.              Scan_Convert_TextureGT();
  778.          break;
  779.  
  780.          case Phong_Texture_Trans:
  781.              _U1         = ThisPolygon->u0;
  782.              _V1         = ThisPolygon->v0;
  783.              _U2         = ThisPolygon->u1;
  784.              _V2         = ThisPolygon->v1;
  785.              _U3         = ThisPolygon->u2;
  786.              _V3         = ThisPolygon->v2;
  787.              _A1         = (ThisPolygon->Vertex[0])->Intensity;
  788.              _A2         = (ThisPolygon->Vertex[1])->Intensity;
  789.              _A3         = (ThisPolygon->Vertex[2])->Intensity;
  790.              _TransLevel = translevel;
  791.              Scan_Convert_TexturePT();
  792.          break;
  793.  
  794.          case WireFrame_Shadow:
  795.              _ColorIndex=ThisPolygon->shadowcolor;           
  796.              Scan_Convert_Wire();
  797.          break;
  798.          
  799.          case Constant_Shadow:   
  800.              _ColorIndex = ThisPolygon->shadowcolor;
  801.              Scan_Convert_Lambert();
  802.          break;
  803.  
  804.          case Lambert_Shadow: 
  805.              _ColorIndex = ThisPolygon->shadowcolor;
  806.              Scan_Convert_Lambert();
  807.          break;
  808.  
  809.          case Gouraud_Shadow:   
  810.              _ColorIndex = ThisPolygon->shadowcolor;
  811.              Scan_Convert_Lambert();
  812.          break;
  813.  
  814.          case Phong_Shadow:
  815.              _ColorIndex = ThisPolygon->shadowcolor;
  816.              Scan_Convert_Lambert();
  817.          break;
  818.          
  819.          case WireFrame_Texture_Shadow:           // just call same function again.
  820.              _ColorIndex=ThisPolygon->shadowcolor;           
  821.              Scan_Convert_Wire();
  822.          break;
  823.  
  824.          case Constant_Texture_Shadow:   
  825.              _ColorIndex = ThisPolygon->shadowcolor;
  826.              Scan_Convert_Lambert();
  827.          break;
  828.  
  829.          case Lambert_Texture_Shadow:
  830.              _ColorIndex = ThisPolygon->shadowcolor;
  831.              Scan_Convert_Lambert();
  832.          break;
  833.  
  834.          case Gouraud_Texture_Shadow:
  835.              _ColorIndex = ThisPolygon->shadowcolor;
  836.              Scan_Convert_Lambert();
  837.          break; 
  838.  
  839.          case Phong_Texture_Shadow:
  840.              _ColorIndex = ThisPolygon->shadowcolor;
  841.              Scan_Convert_Lambert();
  842.          break;
  843.  
  844.          case WireFrame_Trans_Shadow:           
  845.              _ColorIndex=ThisPolygon->shadowcolor;           
  846.              Scan_Convert_Wire();
  847.          break;
  848.  
  849.          case Constant_Trans_Shadow:   
  850.              _ColorIndex = ThisPolygon->shadowcolor;
  851.              _TransLevel = translevel;
  852.              Scan_Convert_LambertT();
  853.          break;
  854.  
  855.          case Lambert_Trans_Shadow:
  856.              _ColorIndex = ThisPolygon->shadowcolor;
  857.              _TransLevel = translevel;
  858.              Scan_Convert_LambertT();
  859.          break;
  860.  
  861.          case Gouraud_Trans_Shadow:
  862.              _ColorIndex = ThisPolygon->shadowcolor;
  863.              _TransLevel = translevel;
  864.              Scan_Convert_LambertT();
  865.          break;
  866.  
  867.          case Phong_Trans_Shadow:
  868.              _ColorIndex = ThisPolygon->shadowcolor;
  869.              _TransLevel = translevel;
  870.              Scan_Convert_LambertT();
  871.          break;
  872.          
  873.          case WireFrame_Texture_Trans_Shadow:        
  874.              _ColorIndex=ThisPolygon->shadowcolor;           
  875.              Scan_Convert_Wire();
  876.          break;
  877.  
  878.          case Constant_Texture_Trans_Shadow:   
  879.              _ColorIndex = ThisPolygon->shadowcolor;
  880.              _TransLevel = translevel;
  881.              Scan_Convert_LambertT();
  882.          break;
  883.  
  884.          case Lambert_Texture_Trans_Shadow:
  885.              _ColorIndex = ThisPolygon->shadowcolor;
  886.              _TransLevel = translevel;
  887.              Scan_Convert_LambertT();
  888.          break;
  889.  
  890.          case Gouraud_Texture_Trans_Shadow:
  891.              _ColorIndex = ThisPolygon->shadowcolor;
  892.              _TransLevel = translevel;
  893.              Scan_Convert_LambertT();
  894.          break;
  895.  
  896.          case Phong_Texture_Trans_Shadow:
  897.              _ColorIndex = ThisPolygon->shadowcolor;
  898.              _TransLevel = translevel;
  899.              Scan_Convert_LambertT();
  900.          break;
  901.  
  902.          case WireFrame_Haze:           
  903.              _ColorIndex=ThisPolygon->color+SHADES;          
  904.              Scan_Convert_Wire();
  905.          break;
  906.  
  907.          case Constant_Haze:   
  908.              _ColorIndex = ThisPolygon->color + (ThisPolygon->Vertex[0])->Intensity;
  909.              _AvgZ       = (long)ThisPolygon->avgz;
  910.              Scan_Convert_LambertH();
  911.          break;
  912.  
  913.          case Lambert_Haze:
  914.              _ColorIndex = ThisPolygon->color + (ThisPolygon->Vertex[0])->Intensity;
  915.              _AvgZ       = (long)ThisPolygon->avgz;
  916.              Scan_Convert_LambertH();
  917.          break;
  918.  
  919.          case Gouraud_Haze:
  920.              _Z1         = (long)z0;
  921.              _Z2         = (long)z1;
  922.              _Z3         = (long)z2;                                       
  923.              _I1         = (ThisPolygon->Vertex[0])->Intensity;
  924.              _I2         = (ThisPolygon->Vertex[1])->Intensity;
  925.              _I3         = (ThisPolygon->Vertex[2])->Intensity;
  926.              _ColorIndex = ThisPolygon->color;
  927.              Scan_Convert_GouraudH();
  928.          break; 
  929.  
  930.          case Phong_Haze:
  931.              _Z1         = (long)z0;
  932.              _Z2         = (long)z1;
  933.              _Z3         = (long)z2;                                       
  934.              _A1         = (ThisPolygon->Vertex[0])->Intensity;
  935.              _A2         = (ThisPolygon->Vertex[1])->Intensity;
  936.              _A3         = (ThisPolygon->Vertex[2])->Intensity;
  937.              _ColorIndex = ThisPolygon->color;
  938.              Scan_Convert_PhongH();
  939.          break;
  940.          
  941.          case WireFrame_Texture_Haze:        
  942.              _ColorIndex=ThisPolygon->color+SHADES;          
  943.              Scan_Convert_Wire();
  944.          break;
  945.  
  946.          case Constant_Texture_Haze:   
  947.              _U1         = ThisPolygon->u0;
  948.              _V1         = ThisPolygon->v0;
  949.              _U2         = ThisPolygon->u1;
  950.              _V2         = ThisPolygon->v1;
  951.              _U3         = ThisPolygon->u2;
  952.              _V3         = ThisPolygon->v2;
  953.              _ColorIndex = SHADES;
  954.              _AvgZ       = (long)ThisPolygon->avgz;
  955.              Scan_Convert_TextureLH();
  956.          break;
  957.  
  958.          case Lambert_Texture_Haze:
  959.              _U1         = ThisPolygon->u0;
  960.              _V1         = ThisPolygon->v0;
  961.              _U2         = ThisPolygon->u1;
  962.              _V2         = ThisPolygon->v1;
  963.              _U3         = ThisPolygon->u2;
  964.              _V3         = ThisPolygon->v2;
  965.              _ColorIndex = (ThisPolygon->Vertex[0])->Intensity;
  966.              _AvgZ       = (long)ThisPolygon->avgz;
  967.              Scan_Convert_TextureLH();
  968.          break;
  969.  
  970.          case Gouraud_Texture_Haze:
  971.              _Z1         = (long)z0;
  972.              _Z2         = (long)z1;
  973.              _Z3         = (long)z2;                                       
  974.              _U1         = ThisPolygon->u0;
  975.              _V1         = ThisPolygon->v0;
  976.              _U2         = ThisPolygon->u1;
  977.              _V2         = ThisPolygon->v1;
  978.              _U3         = ThisPolygon->u2;
  979.              _V3         = ThisPolygon->v2;
  980.              _I1         = (ThisPolygon->Vertex[0])->Intensity;
  981.              _I2         = (ThisPolygon->Vertex[1])->Intensity;
  982.              _I3         = (ThisPolygon->Vertex[2])->Intensity;
  983.              Scan_Convert_TextureGH();
  984.          break;
  985.  
  986.          case Phong_Texture_Haze:
  987.              _Z1         = (long)z0;
  988.              _Z2         = (long)z1;
  989.              _Z3         = (long)z2;                                       
  990.              _U1         = ThisPolygon->u0;
  991.              _V1         = ThisPolygon->v0;
  992.              _U2         = ThisPolygon->u1;
  993.              _V2         = ThisPolygon->v1;
  994.              _U3         = ThisPolygon->u2;
  995.              _V3         = ThisPolygon->v2;
  996.              _A1         = (ThisPolygon->Vertex[0])->Intensity;
  997.              _A2         = (ThisPolygon->Vertex[1])->Intensity;
  998.              _A3         = (ThisPolygon->Vertex[2])->Intensity;
  999.              Scan_Convert_TexturePH();
  1000.          break;
  1001.  
  1002.          case WireFrame_Shadow_Haze:
  1003.              _ColorIndex=ThisPolygon->shadowcolor;           
  1004.              Scan_Convert_Wire();
  1005.          break;
  1006.  
  1007.          case Constant_Shadow_Haze:   
  1008.              _ColorIndex = ThisPolygon->shadowcolor;
  1009.              _AvgZ       = (long)ThisPolygon->avgz;
  1010.              Scan_Convert_LambertH();
  1011.          break;
  1012.  
  1013.          case Lambert_Shadow_Haze:
  1014.              _ColorIndex = ThisPolygon->shadowcolor;
  1015.              _AvgZ       = (long)ThisPolygon->avgz;
  1016.              Scan_Convert_LambertH();
  1017.          break;
  1018.  
  1019.          case Gouraud_Shadow_Haze:
  1020.              _ColorIndex = ThisPolygon->shadowcolor;
  1021.              _AvgZ       = (long)ThisPolygon->avgz;
  1022.              Scan_Convert_LambertH();
  1023.          break;
  1024.  
  1025.          case Phong_Shadow_Haze:
  1026.              _ColorIndex = ThisPolygon->shadowcolor;
  1027.              _AvgZ       = (long)ThisPolygon->avgz;
  1028.              Scan_Convert_LambertH();
  1029.          break;
  1030.          
  1031.          case WireFrame_Texture_Shadow_Haze:
  1032.              _ColorIndex=ThisPolygon->shadowcolor;           
  1033.              Scan_Convert_Wire();
  1034.          break;
  1035.  
  1036.          case Constant_Texture_Shadow_Haze:   
  1037.              _ColorIndex = ThisPolygon->shadowcolor;
  1038.              _AvgZ       = (long)ThisPolygon->avgz;
  1039.              Scan_Convert_LambertH();
  1040.          break;
  1041.  
  1042.          case Lambert_Texture_Shadow_Haze:
  1043.              _ColorIndex = ThisPolygon->shadowcolor;
  1044.              _AvgZ       = (long)ThisPolygon->avgz;
  1045.              Scan_Convert_LambertH();
  1046.          break;
  1047.  
  1048.          case Gouraud_Texture_Shadow_Haze:
  1049.              _ColorIndex = ThisPolygon->shadowcolor;
  1050.              _AvgZ       = (long)ThisPolygon->avgz;
  1051.              Scan_Convert_LambertH();
  1052.          break;
  1053.  
  1054.          case Phong_Texture_Shadow_Haze:
  1055.              _ColorIndex = ThisPolygon->shadowcolor;
  1056.              _AvgZ       = (long)ThisPolygon->avgz;
  1057.              Scan_Convert_LambertH();
  1058.          break;
  1059.       }
  1060.     }
  1061. }
  1062.  
  1063. OBJECTCLASS::OBJECTCLASS(void)              // Constructor.
  1064. {
  1065.   NextObject = NULL;
  1066. }
  1067.  
  1068. OBJECTCLASS::~OBJECTCLASS(void)             // Destructor.
  1069. {
  1070.  
  1071. }
  1072.  
  1073. OBJECTCLASS *OBJECTCLASS::CreateMorphData(void)
  1074. {
  1075.    POINT3D *LCoordSource,*LCoordDest;
  1076.  
  1077.    LCoordSource = MorphSource->LocalCoord;
  1078.    LCoordDest   = (MorphSource->NextMorphObject)->LocalCoord;
  1079.  
  1080.    int start,end,count;
  1081.    switch (SHADING)
  1082.    {
  1083.      case Gouraud:
  1084.        start=0;
  1085.        end=numvertices;
  1086.      break;
  1087.      case Phong:
  1088.        start=0;
  1089.        end=numvertices;
  1090.      break;
  1091.      default:
  1092.        start=0;
  1093.        end=numvertices/2;   // don't need to morph avgnormals for these.
  1094.      break;
  1095.    }
  1096.    
  1097.    for (count=start;count<end;count++)
  1098.    {
  1099.      LCoordSource[count].morphx  = 0;           // reset. how much to add to each vertices when morphing.
  1100.      LCoordSource[count].morphy  = 0;
  1101.      LCoordSource[count].morphz  = 0;
  1102.        
  1103.      LCoordSource[count].morphdx = ( LCoordDest[count].x -
  1104.                                      LCoordSource[count].x )
  1105.                                      * morphsteps;
  1106.      LCoordSource[count].morphdy = ( LCoordDest[count].y -
  1107.                                      LCoordSource[count].y )
  1108.                                      * morphsteps;
  1109.      LCoordSource[count].morphdz = ( LCoordDest[count].z -
  1110.                                      LCoordSource[count].z )
  1111.                                      * morphsteps;
  1112.    }
  1113.    
  1114.    OBJECTCLASS *temp;
  1115.    temp = MorphSource;
  1116.    MorphSource  = MorphSource->NextMorphObject;    // move source to next object.
  1117.  
  1118.    return (temp);    // return present source object.
  1119. }
  1120.  
  1121. OBJECTCLASS *OBJECTCLASS::GetMorphObject(void)
  1122. {
  1123.   static float morphcount = 1.0;               // CreateMorphData first time through.
  1124.   static OBJECTCLASS *morphObject = NULL;
  1125.  
  1126.   if (MORPHING)
  1127.   {  
  1128.      morphcount += morphsteps;          // inc count
  1129.  
  1130.      if (morphcount > 1.0)   // reset.
  1131.      {
  1132.         morphObject=CreateMorphData();
  1133.         morphcount = 0.0;
  1134.      }
  1135.   }
  1136.   else
  1137.   {
  1138.      morphObject=this;           // if Morphing not enabled, just return root object.
  1139.      MorphSource=this;           // reset MorphSource to root (just in case it changed when morphing).
  1140.   }
  1141.  
  1142.   return (morphObject);    
  1143. }
  1144.  
  1145. void OBJECTCLASS::GetCenterStats(float *radius, float *xsphere, float *ysphere,
  1146.                                  float *zsphere)
  1147. {
  1148.   *radius=this->radius;
  1149.   *xsphere=this->xsphere;        // in camera coords.
  1150.   *ysphere=this->ysphere;
  1151.   *zsphere=this->zsphere;
  1152. }
  1153.     
  1154. void OBJECTCLASS::TransformObject(MATRIX TSR_Matrix)
  1155. {
  1156.     float x,y,z;
  1157.     int index,start,end;
  1158.     
  1159.     switch (SHADING)
  1160.     {
  1161.       case Gouraud:
  1162.         start=0;
  1163.         end=numvertices;
  1164.       break;
  1165.       case Phong:
  1166.         start=0;
  1167.         end=numvertices;
  1168.       break;
  1169.       default:
  1170.         start=0;
  1171.         end=numvertices/2;
  1172.       break;
  1173.     }
  1174.       
  1175.     POINT3D *LCoord,*CCoord;
  1176.     switch (MORPHING)
  1177.     {
  1178.       case TRUE:        
  1179.         for (index=start;index<end;index++)
  1180.         {
  1181.            LCoord = &( LocalCoord[index] );
  1182.            CCoord = &( CameraCoord[index] );
  1183.            
  1184.            LCoord->morphx += LCoord->morphdx;     // get closer to destination object.
  1185.            LCoord->morphy += LCoord->morphdy; 
  1186.            LCoord->morphz += LCoord->morphdz; 
  1187.  
  1188.            x = LCoord->x + LCoord->morphx;
  1189.            y = LCoord->y + LCoord->morphy;
  1190.            z = LCoord->z + LCoord->morphz;
  1191.  
  1192.            CCoord->x = x*TSR_Matrix[0][0]+
  1193.                        y*TSR_Matrix[1][0]+
  1194.                        z*TSR_Matrix[2][0];
  1195.  
  1196.            CCoord->y = x*TSR_Matrix[0][1]+
  1197.                        y*TSR_Matrix[1][1]+
  1198.                        z*TSR_Matrix[2][1];
  1199.  
  1200.            CCoord->z = x*TSR_Matrix[0][2]+
  1201.                        y*TSR_Matrix[1][2]+
  1202.                        z*TSR_Matrix[2][2];
  1203.  
  1204.            CCoord->valid = FALSE;         // this is used for Gouraud and Phong shading when morphing.
  1205.                                           // reset valid flag. Because when morphing the avgnormal
  1206.                                           // goes out of whack and needs to be renormalized.
  1207.         }
  1208.       break;
  1209.  
  1210.       case FALSE:
  1211.         for (index=start;index<end;index++)
  1212.         {         
  1213.            LCoord = &( LocalCoord[index] );
  1214.            CCoord = &( CameraCoord[index] );
  1215.  
  1216.            x = LCoord->x;         // don't mess with local coords.
  1217.            y = LCoord->y;
  1218.            z = LCoord->z;
  1219.  
  1220.            CCoord->x = x*TSR_Matrix[0][0]+
  1221.                        y*TSR_Matrix[1][0]+
  1222.                        z*TSR_Matrix[2][0];
  1223.  
  1224.            CCoord->y = x*TSR_Matrix[0][1]+
  1225.                        y*TSR_Matrix[1][1]+
  1226.                        z*TSR_Matrix[2][1];
  1227.  
  1228.            CCoord->z = x*TSR_Matrix[0][2]+
  1229.                        y*TSR_Matrix[1][2]+
  1230.                        z*TSR_Matrix[2][2];
  1231.  
  1232.            CCoord->valid = FALSE;         // this is used for Gouraud shading when morphing. And for Phong shading.
  1233.                                           // reset valid flag. Because when morphing the avgnormal
  1234.                                           // goes out of whack and needs to be renormalized.
  1235.         }
  1236.       break;
  1237.     }
  1238. }       
  1239.  
  1240. void OBJECTCLASS::Local2Camera(MATRIX CameraMatrix, int Mode)
  1241. {
  1242.    int index,start,end;
  1243.    float x,y,z;
  1244.  
  1245.    switch (Mode)
  1246.    {
  1247.      case CENTER:            // just transform object center --> camera.
  1248.  
  1249.        x=worldx;
  1250.        y=worldy;
  1251.        z=worldz;
  1252.               
  1253.        xsphere =              x*CameraMatrix[0][0]+
  1254.                               y*CameraMatrix[1][0]+
  1255.                               z*CameraMatrix[2][0]+
  1256.                                 CameraMatrix[3][0];
  1257.                                       
  1258.        ysphere =              x*CameraMatrix[0][1]+
  1259.                               y*CameraMatrix[1][1]+
  1260.                               z*CameraMatrix[2][1]+
  1261.                                 CameraMatrix[3][1];
  1262.  
  1263.        zsphere =              x*CameraMatrix[0][2]+
  1264.                               y*CameraMatrix[1][2]+
  1265.                               z*CameraMatrix[2][2]+
  1266.                                 CameraMatrix[3][2];
  1267.      break;
  1268.        
  1269.      case VERTICES:
  1270.  
  1271.        switch (SHADING)
  1272.        {
  1273.           case Gouraud:
  1274.             start=0;
  1275.             end=numvertices;
  1276.           break;
  1277.           case Phong:
  1278.             start=0;
  1279.             end=numvertices;
  1280.           break;
  1281.           default:
  1282.             start=0;
  1283.             end=numvertices/2;
  1284.           break;
  1285.        }
  1286.  
  1287.         POINT3D *CCoord;       
  1288.         for (index=start;index<end;index++)
  1289.         {
  1290.            CCoord = &( CameraCoord[index] );
  1291.            
  1292.            x = CCoord->x + worldx;
  1293.            y = CCoord->y + worldy;
  1294.            z = CCoord->z + worldz;
  1295.  
  1296.            CCoord->x = x*CameraMatrix[0][0]+
  1297.                        y*CameraMatrix[1][0]+
  1298.                        z*CameraMatrix[2][0]+
  1299.                          CameraMatrix[3][0];
  1300.  
  1301.            CCoord->y = x*CameraMatrix[0][1]+
  1302.                        y*CameraMatrix[1][1]+
  1303.                        z*CameraMatrix[2][1]+
  1304.                          CameraMatrix[3][1];
  1305.  
  1306.            CCoord->z = x*CameraMatrix[0][2]+
  1307.                        y*CameraMatrix[1][2]+
  1308.                        z*CameraMatrix[2][2]+
  1309.                          CameraMatrix[3][2];
  1310.  
  1311.         }
  1312.      break;
  1313.      
  1314.    }  // end switch.
  1315. }
  1316.  
  1317. void OBJECTCLASS::HSR_Shade(POINT3D *viewpoint, POINT3D *lightsource)
  1318. {
  1319.  
  1320.     POINT3D normal, avgnormal, sightvector, lightvector, u, v;
  1321.     POINT3D **VertexId;
  1322.     POLYGONCLASS *ThisPolygon;
  1323.     int pindex, vindex, intensity;
  1324.     float angle, highlight;
  1325.  
  1326.      for (pindex=0;pindex<numpoly;pindex++)
  1327.      { 
  1328.         ThisPolygon = &(Polygon[pindex]);        // alias for ease of access.
  1329.         VertexId = ThisPolygon->Vertex;
  1330.         
  1331.         MakeVector(VertexId[0],viewpoint,&sightvector);
  1332.         
  1333.         MakeVector(VertexId[0],VertexId[1],&u);
  1334.         MakeVector(VertexId[0],VertexId[2],&v);
  1335.         CrossProduct(&u,&v,&normal);
  1336.  
  1337.         if (SHADOWING) 
  1338.           CopyPoint3D(&normal,&(ThisPolygon->Normal));    // save. Use later on if Shadows are enabled.
  1339.         
  1340.         angle=DotProduct(&normal,&sightvector);
  1341.         
  1342.         if (angle>0)             // acute, visible!
  1343.         {
  1344.           ThisPolygon->visible = TRUE;
  1345.  
  1346.           switch (SHADING)
  1347.           {
  1348.              case WireFrame:                            // no shading needed.
  1349.              break;
  1350.              
  1351.              case Constant:                             // midpoint is the actual color.
  1352.  
  1353.                (VertexId[0])->Intensity = HALF_SHADES;
  1354.  
  1355.              break;
  1356.  
  1357.              case Lambert:
  1358.  
  1359.                MakeVector(VertexId[0],lightsource,&lightvector);
  1360.                Normalize(&lightvector);
  1361.                
  1362.                angle=DotProduct(&normal,&lightvector);
  1363.  
  1364.                if (angle>0)  // light is hitting the polygon.
  1365.                {
  1366.                   highlight = (SHADES*angle)*ThisPolygon->Normalength;
  1367.                   if ( (intensity = AMBIENT + highlight) > SHADES)
  1368.                         intensity = SHADES;
  1369.                   (VertexId[0])->Intensity = (int)intensity;
  1370.                }
  1371.                else
  1372.                  (VertexId[0])->Intensity = AMBIENT;
  1373.  
  1374.              break;       
  1375.  
  1376.              case Gouraud:           
  1377.  
  1378.                for (vindex=0;vindex<3;vindex++)  // cycle through each vertex in poly.
  1379.                {
  1380.                   MakeVector(VertexId[vindex],lightsource,&lightvector);
  1381.                   Normalize(&lightvector);
  1382.  
  1383.                   MakeVector(VertexId[vindex],ThisPolygon->AvgNormal[vindex],&avgnormal);
  1384.  
  1385.                   if (MORPHING)
  1386.                     Normalize(&avgnormal);     // because when interpolating, avgnormals goes out of whack.
  1387.  
  1388.                   angle=DotProduct(&avgnormal,&lightvector);
  1389.                   if (angle>0)  // light is hitting the polygon.
  1390.                   {
  1391.                      if ( (intensity = AMBIENT + SHADES*angle) > SHADES)
  1392.                        intensity = SHADES;
  1393.                      (VertexId[vindex])->Intensity = (int)intensity;
  1394.                   }
  1395.                   else
  1396.                     (VertexId[vindex])->Intensity = AMBIENT;
  1397.                }
  1398.  
  1399.              break;
  1400.  
  1401.              case Phong:
  1402.                for (vindex=0;vindex<3;vindex++)  // cycle through each vertex in poly.
  1403.                {
  1404.                   MakeVector(VertexId[vindex],lightsource,&lightvector);
  1405.                   Normalize(&lightvector);
  1406.  
  1407.                   MakeVector(VertexId[vindex],ThisPolygon->AvgNormal[vindex],&avgnormal);
  1408.  
  1409.                   if (MORPHING)
  1410.                     Normalize(&avgnormal);     // because when interpolating, avgnormals goes out of whack.
  1411.  
  1412.                   angle=DotProduct(&avgnormal,&lightvector);
  1413.                   if (angle>0)  // light is hitting the polygon.
  1414.                   {
  1415.                      if (!(VertexId[vindex])->valid)
  1416.                      {
  1417.                         angle -= 0.00005;   // This is a bit of a kludge. Acos only accepts values between -1 and 1.
  1418.                                             // However the value sometime comes to 1.00000011920929. Really 1 but acos doesn't like it.
  1419.                                             // I could fix this by having more percision in my other routines but what the hell?
  1420.  
  1421.                         angle = (float)acos( (double)angle )*RADIANS_TO_DEGREES;    // get actual angle between light and normal vector!                        
  1422.                         (VertexId[vindex])->Intensity = (int)angle;  
  1423.                         (VertexId[vindex])->valid = TRUE;    // we already got angle for this avgnormal.
  1424.                      }
  1425.                   }
  1426.                   else
  1427.                     (VertexId[vindex])->Intensity = AMBIENTANGLE;
  1428.                }
  1429.  
  1430.              break;
  1431.           }  // end switch.     
  1432.         }  // end if visible
  1433.         else
  1434.           ThisPolygon->visible = FALSE;
  1435.      }   // end for loop
  1436. }
  1437.  
  1438. void OBJECTCLASS::DoShadows(POINT3D *lightsource)
  1439.   int vindex,pindex;
  1440.   float angle,slope;
  1441.   POINT3D lightvector, **VertexId;
  1442.   POLYGONCLASS *ThisPolygon;
  1443.  
  1444.    if (SHADOWING)                  // only do if enabled.
  1445.    {            
  1446.      for(pindex=0;pindex<numpoly;pindex++)
  1447.      {
  1448.          ThisPolygon = &(Polygon[pindex]);      
  1449.          angle=DotProduct(&(ThisPolygon->Normal),lightsource);
  1450.         
  1451.          if (angle>0)             // visible! Do Shadows.
  1452.          {
  1453.            ThisPolygon->shadowvisible = Shadow;
  1454.            VertexId = ThisPolygon->Vertex;
  1455.            for(vindex=0;vindex<3;vindex++)
  1456.            {
  1457.               MakeVector( VertexId[vindex], lightsource, &lightvector); 
  1458.               Normalize(&lightvector);
  1459.               
  1460.               slope = 600/lightvector.z;      // set shadow 600 units away from object. (looks pretty nice that far.)
  1461.  
  1462.               (ThisPolygon->shadow[vindex]).x = (VertexId[vindex])->x + slope*lightvector.x;
  1463.               (ThisPolygon->shadow[vindex]).y = (VertexId[vindex])->y + slope*lightvector.y;
  1464.               (ThisPolygon->shadow[vindex]).z = (VertexId[vindex])->z + 200;     // to look good when doing perspective correction.
  1465.  
  1466.            }
  1467.            MeshList[meshindex] = ThisPolygon;         // add to beginning of rendering list (drawn first).
  1468.            meshindex++;
  1469.            shadowindex++;                             // how many shadows in scene.
  1470.          }
  1471.          else
  1472.            ThisPolygon->shadowvisible = NoShadow;
  1473.      } // end for.         
  1474.    } // end if SHADOW.
  1475. }
  1476.  
  1477. void OBJECTCLASS::PolyCull(int Mode)
  1478. {
  1479.  
  1480.    int index;
  1481.    float x1,x2,x3,y1,y2,y3,z1,z2,z3;
  1482.    float compare1,compare2,compare3;
  1483.    POLYGONCLASS *ThisPolygon;
  1484.  
  1485.    switch (Mode)
  1486.    {
  1487.       case CULL_Z:
  1488.         for (index=0;index<this->numpoly;index++)
  1489.         {
  1490.            ThisPolygon = &(this->Polygon[index]);
  1491.            if (ThisPolygon->visible)
  1492.            {                               // extract z component.
  1493.                 z1=(ThisPolygon->Vertex[0])->z;
  1494.                 z2=(ThisPolygon->Vertex[1])->z;
  1495.                 z3=(ThisPolygon->Vertex[2])->z;
  1496.  
  1497.                 if ( (z1>HITHER_Z || z2>HITHER_Z || z3>HITHER_Z) &&
  1498.                      (z1<YON_Z || z2<YON_Z || z3<YON_Z) )
  1499.                 {
  1500.                    MeshList[meshindex]=ThisPolygon;    // it's visible, add
  1501.                    meshindex++;                        // to meshlist for rendering.
  1502.                 }
  1503.            }
  1504.         }
  1505.       break;
  1506.       case CULL_XYZ:           // do full polygon culling to frustrum.
  1507.         for (index=0;index<this->numpoly;index++)
  1508.         {
  1509.            ThisPolygon = &(this->Polygon[index]);
  1510.            if (ThisPolygon->visible)    // only do if visible.
  1511.            {
  1512.                 
  1513.               x1=(ThisPolygon->Vertex[0])->x;      // extract cameracoords for clipping.
  1514.               x2=(ThisPolygon->Vertex[1])->x;
  1515.               x3=(ThisPolygon->Vertex[2])->x;
  1516.                 
  1517.               y1=(ThisPolygon->Vertex[0])->y;
  1518.               y2=(ThisPolygon->Vertex[1])->y;
  1519.               y3=(ThisPolygon->Vertex[2])->y;
  1520.  
  1521.               z1=(ThisPolygon->Vertex[0])->z;
  1522.               z2=(ThisPolygon->Vertex[1])->z;
  1523.               z3=(ThisPolygon->Vertex[2])->z;
  1524.         
  1525.               if (!((z1>HITHER_Z || z2>HITHER_Z || z3>HITHER_Z) &&
  1526.                     (z1<YON_Z || z2<YON_Z || z3<YON_Z)))
  1527.               {
  1528.                     // is clipped --> don't add to MeshList.
  1529.                   continue;
  1530.               }
  1531.                 
  1532.               compare1=HALF_SCREEN_WIDTH_VD*z1;
  1533.               compare2=HALF_SCREEN_WIDTH_VD*z2;
  1534.               compare3=HALF_SCREEN_WIDTH_VD*z3;
  1535.                 
  1536.               if  (!((x1>-compare1 || x2>-compare2 || x3>-compare3) &&
  1537.                      (x1<compare1 || x2<compare2 || x3<compare3)))
  1538.               {
  1539.                      // is clipped --> don't add to MeshList.
  1540.                  continue;
  1541.               }
  1542.  
  1543.               compare1=HALF_SCREEN_HEIGHT_VD*z1;
  1544.               compare2=HALF_SCREEN_HEIGHT_VD*z2;
  1545.               compare3=HALF_SCREEN_HEIGHT_VD*z3;
  1546.  
  1547.               if  (!((y1>-compare1 || y2>-compare2 || y3>-compare3) &&
  1548.                      (y1<compare1 || y2<compare2 || y3<compare3)))
  1549.               {
  1550.                     // is clipped --> don't add to MeshList.
  1551.                   continue;
  1552.               }
  1553.  
  1554.              MeshList[meshindex]=ThisPolygon;      // visible, so add to List.
  1555.              meshindex++;
  1556.            }  // end if visible.
  1557.         }   // end for loop.
  1558.       break;
  1559.    }
  1560. }             
  1561.             
  1562. void OBJECTCLASS::PreComputeNormal(int vertex0, int vertex1, int vertex2, int index)
  1563. {
  1564.     POINT3D u,v,normal;
  1565.     POINT3D *Vertex;
  1566.  
  1567.     Vertex=this->LocalCoord;
  1568.     
  1569.     MakeVector(&(Vertex[vertex0]),&(Vertex[vertex1]),&u);
  1570.     MakeVector(&(Vertex[vertex0]),&(Vertex[vertex2]),&v);
  1571.     CrossProduct(&u,&v,&normal);
  1572.     Normalize(&normal);                     // normalize it!
  1573.                                             // get new normal point.
  1574.                                             // and save in vertex list.
  1575.     Vertex[index].x = Vertex[vertex0].x + normal.x;
  1576.     Vertex[index].y = Vertex[vertex0].y + normal.y;
  1577.     Vertex[index].z = Vertex[vertex0].z + normal.z;
  1578. }
  1579.  
  1580. void OBJECTCLASS::ComputeNormalength(int vertex0, int vertex1, int vertex2,
  1581.                                      POLYGONCLASS *ThisPolygon)
  1582. {
  1583.     POINT3D u,v,normal;
  1584.     POINT3D *Vertex;
  1585.  
  1586.     Vertex=this->LocalCoord;
  1587.     
  1588.     MakeVector(&(Vertex[vertex0]),&(Vertex[vertex1]),&u);
  1589.     MakeVector(&(Vertex[vertex0]),&(Vertex[vertex2]),&v);
  1590.     CrossProduct(&u,&v,&normal);
  1591.  
  1592.     ThisPolygon->Normalength = 1/Magnitude(&normal);
  1593. }
  1594.  
  1595. void OBJECTCLASS::PreComputeAvgNormal(struct tempstruct *polystats)
  1596. {
  1597.   int vertex0, vertex1, vertex2, commvertex, count, pindex, avgindex;
  1598.   int Found=FALSE;
  1599.   float sum;
  1600.   POINT3D u, v, normal, avgnormal;
  1601.   
  1602.     avgindex=numvertices;       // start of avgnormals.
  1603.  
  1604.     POINT3D *LCoord;
  1605.     LCoord = LocalCoord;
  1606.                                                      
  1607.     for(commvertex=0;commvertex<numvertices;commvertex++)
  1608.     {
  1609.         avgnormal.x=0; avgnormal.y=0; avgnormal.z=0;    // reset.
  1610.         count=0;
  1611.                                   // look for polys that have a common vertex.
  1612.         for(pindex=0;pindex<numpoly;pindex++)
  1613.         {     
  1614.              vertex0=polystats[pindex].p0;
  1615.              vertex1=polystats[pindex].p1;
  1616.              vertex2=polystats[pindex].p2; 
  1617.            
  1618.            if (vertex0 == commvertex)
  1619.            {
  1620.              Found=TRUE;
  1621.  
  1622.              MakeVector( &(LCoord[vertex0]), &(LCoord[vertex1]), &u );
  1623.              MakeVector( &(LCoord[vertex0]), &(LCoord[vertex2]), &v );
  1624.              CrossProduct(&u,&v,&normal);
  1625.  
  1626.              Polygon[pindex].AvgNormal[0] = &(CameraCoord[avgindex]);
  1627.            }
  1628.            else
  1629.            if (vertex1 == commvertex)
  1630.            {
  1631.              Found=TRUE;
  1632.  
  1633.              MakeVector( &(LCoord[vertex1]), &(LCoord[vertex2]), &u );
  1634.              MakeVector( &(LCoord[vertex1]), &(LCoord[vertex0]), &v );
  1635.              CrossProduct(&u,&v,&normal);
  1636.  
  1637.              Polygon[pindex].AvgNormal[1] = &(CameraCoord[avgindex]);
  1638.            }
  1639.            else
  1640.            if (vertex2 == commvertex)
  1641.            {
  1642.              Found=TRUE;
  1643.  
  1644.              MakeVector( &(LCoord[vertex2]), &(LCoord[vertex0]), &u );
  1645.              MakeVector( &(LCoord[vertex2]), &(LCoord[vertex1]), &v );
  1646.              CrossProduct(&u,&v,&normal);
  1647.  
  1648.              Polygon[pindex].AvgNormal[2] = &(CameraCoord[avgindex]);
  1649.            }
  1650.                
  1651.            if (Found)
  1652.            {
  1653.               Found=FALSE;
  1654.               count++;
  1655.               avgnormal.x+=normal.x;
  1656.               avgnormal.y+=normal.y;
  1657.               avgnormal.z+=normal.z;
  1658.             }
  1659.         }  // end for (pindex).
  1660.  
  1661.         if (count > 0)         // Weired. Some objects don't have all vertices used.
  1662.         {
  1663.           sum=1/(float)count;
  1664.           avgnormal.x = avgnormal.x * sum;
  1665.           avgnormal.y = avgnormal.y * sum;
  1666.           avgnormal.z = avgnormal.z * sum;
  1667.         
  1668.           Normalize(&avgnormal);
  1669.  
  1670.           LCoord[avgindex].x = LCoord[commvertex].x + avgnormal.x;
  1671.           LCoord[avgindex].y = LCoord[commvertex].y + avgnormal.y;
  1672.           LCoord[avgindex].z = LCoord[commvertex].z + avgnormal.z;
  1673.         }
  1674.       avgindex++;
  1675.     }
  1676. }
  1677.  
  1678. void OBJECTCLASS::ComputeRadius(void)
  1679. {
  1680.    int index;
  1681.    double x,y,z,radius, new_radius,scale;
  1682.  
  1683.    radius = 0;
  1684.    
  1685.    for (index=0;index<this->numvertices;index++)
  1686.    {
  1687.       x=(double)this->LocalCoord[index].x;
  1688.       y=(double)this->LocalCoord[index].y;
  1689.       z=(double)this->LocalCoord[index].z;
  1690.  
  1691.       new_radius=(float)sqrt( x*x + y*y + z*z );
  1692.       if (new_radius>radius)
  1693.       {
  1694.          radius=new_radius;
  1695.       }
  1696.    }
  1697.  
  1698.    scale=100/radius;             // scale it to a good amount.
  1699.  
  1700.    for (index=0;index<this->numvertices;index++)
  1701.    {
  1702.       this->LocalCoord[index].x=this->LocalCoord[index].x*scale;
  1703.       this->LocalCoord[index].y=this->LocalCoord[index].y*scale;
  1704.       this->LocalCoord[index].z=this->LocalCoord[index].z*scale;
  1705.    }
  1706.    
  1707.    this->radius=radius*scale;
  1708.    this->maxz=this->maxz*scale;
  1709. }
  1710.  
  1711. void OBJECTCLASS::FindCenter(void)
  1712. {
  1713.      POINT3D *Vertex;
  1714.      int count;
  1715.      
  1716.      Vertex = this->LocalCoord;
  1717.      
  1718.      float minx,miny,minz;
  1719.      minx=Vertex[0].x;
  1720.      miny=Vertex[0].y;
  1721.      minz=Vertex[0].z;
  1722.              
  1723.      for (count=1;count<this->numvertices;count++)       // find min x,y,z;
  1724.      {
  1725.        if ( Vertex[count].x < minx )
  1726.          minx=Vertex[count].x;
  1727.        if ( Vertex[count].y < miny )
  1728.          miny=Vertex[count].y;
  1729.        if ( Vertex[count].z < minz )
  1730.          minz=Vertex[count].z;
  1731.      }
  1732.  
  1733.      float maxx,maxy,maxz;
  1734.      maxx=Vertex[0].x;
  1735.      maxy=Vertex[0].y;
  1736.      maxz=Vertex[0].z;
  1737.              
  1738.      for (count=1;count<this->numvertices;count++)       // find max x,y,z;
  1739.      {
  1740.        if ( Vertex[count].x > maxx )
  1741.          maxx=Vertex[count].x;
  1742.        if ( Vertex[count].y > maxy )
  1743.          maxy=Vertex[count].y;
  1744.        if ( Vertex[count].z > maxz)
  1745.          maxz=Vertex[count].z;
  1746.      }
  1747.  
  1748.      float worldx,worldy,worldz;
  1749.      worldx=(minx+maxx)/(float)2;
  1750.      worldy=(miny+maxy)/(float)2;
  1751.      worldz=(minz+maxz)/(float)2;
  1752.  
  1753.      for (count=0;count<this->numvertices;count++)    // adjust local so it
  1754.      {                                                // will be centered around 0,0,0
  1755.         Vertex[count].x-=worldx;
  1756.         Vertex[count].y-=worldy;
  1757.         Vertex[count].z-=worldz;
  1758.      }
  1759.  
  1760.    this->worldx=0;
  1761.    this->worldy=0;
  1762.    this->worldz=250;
  1763.    this->maxz=maxz;
  1764. }
  1765.  
  1766. POLYGONCLASS::POLYGONCLASS(void)              // Constructor.
  1767. {
  1768.   
  1769. }
  1770.  
  1771. POLYGONCLASS::~POLYGONCLASS(void)             // Destructor.
  1772. {
  1773.  
  1774. }
  1775.  
  1776. void MakeVector(POINT3D *init, POINT3D *term, POINT3D *vector)
  1777. {
  1778.     vector->x = term->x - init->x;
  1779.     vector->y = term->y - init->y;
  1780.     vector->z = term->z - init->z;
  1781. }
  1782.  
  1783. void CrossProduct(POINT3D *u, POINT3D *v, POINT3D *normal)
  1784. {
  1785.     normal->x =  u->y*v->z - u->z*v->y;
  1786.     normal->y = -(u->x*v->z - u->z*v->x);
  1787.     normal->z =  u->x*v->y - u->y*v->x;
  1788. }
  1789.  
  1790. float Magnitude(POINT3D *vector)
  1791. {
  1792.     double x,y,z;
  1793.  
  1794.     x=(double)vector->x; y=(double)vector->y; z=(double)vector->z;
  1795.     return( (float)sqrt( x*x+y*y+z*z) );
  1796. }
  1797.  
  1798. void Normalize(POINT3D *vector)
  1799. {
  1800.     double x,y,z,length;
  1801.  
  1802.     x=(double)vector->x; y=(double)vector->y; z=(double)vector->z;
  1803.  
  1804.     length=(float)sqrt( x*x+y*y+z*z );
  1805.     if (length == 0)
  1806.       length = 1;
  1807.  
  1808.     vector->x/=length; vector->y/=length; vector->z/=length;
  1809. }
  1810.  
  1811. float DotProduct(POINT3D *u, POINT3D *v)
  1812. {
  1813.     return( u->x*v->x + u->y*v->y + u->z*v->z );
  1814. }
  1815.  
  1816. void CopyPoint3D(POINT3D *source, POINT3D *dest)
  1817. {
  1818.     dest->x = source->x;
  1819.     dest->y = source->y;
  1820.     dest->z = source->z;
  1821. }
  1822.  
  1823. void BenchMark(int type)
  1824. {
  1825.   _X1=100;              // 25 pixels per polygon.
  1826.   _Y1=100;
  1827.   _X2=107;
  1828.   _Y2=100;
  1829.   _X3=100;
  1830.   _Y3=105;
  1831.   
  1832.   switch (type)
  1833.   {
  1834.  
  1835.     case Lambert:  
  1836.       _ColorIndex = 370;
  1837.       Scan_Convert_Lambert();
  1838.     break;
  1839.  
  1840.     case Gouraud:
  1841.       _ColorIndex=16128;
  1842.       _I1=10;
  1843.       _I2=50;
  1844.       _I3=35;
  1845.       Scan_Convert_Gouraud();
  1846.     break;
  1847.  
  1848.     case Phong:
  1849.       Scan_Convert_Phong();
  1850.     break;
  1851.  
  1852.     case Lambert_Texture:
  1853.     break;
  1854.  
  1855.     case Gouraud_Texture:
  1856.     break;
  1857.  
  1858.     case Phong_Texture:
  1859.     break;
  1860.  
  1861.     default:
  1862.     break;
  1863.   }
  1864. }
  1865.